package com.hxgis.common.service.impl;

import com.es.common.EsAggCondition;
import com.es.common.domain.EsCondition;
import com.es.wrapper.DataWrapper;
import com.hxgis.common.conare.RainstormArea;
import com.hxgis.common.conare.RainstormTime;
import com.hxgis.common.entity.RainstormInfo;
import com.hxgis.common.repository.RainstormInfoRepository;
import com.hxgis.common.service.RainstormCountService;
import com.hxgis.common.utils.CollectionUtils;
import com.hxgis.common.utils.RectField;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * 暴雨计算统计接口 持续性暴雨事件
 */
@Service
@Slf4j
public class RainstormCountServiceImpl implements RainstormCountService {

    @Autowired
    RainstormInfoRepository rainstormInfoRepository;

    public List<RainstormInfo> selectList(String startTime, String endTime,String ... stationNos){
        EsAggCondition esAggCondition = EsAggCondition.getInstance();
        esAggCondition.Group("courseNum").size(100000);
        esAggCondition.getCondition()
                .GTE("time", Long.valueOf(startTime))
                .LTE("time", Long.valueOf(endTime))
                .in("stationNo",stationNos)
                .eq("courseNum",null).not();

        List<String> courseNumList = rainstormInfoRepository.selectListAgg(esAggCondition, new DataWrapper<String>() {
            @Override
            public String wrapper(Map<String, Object> data) {
                return (String) data.get("courseNum");
            }
        });
        EsCondition courseNumCondition = EsCondition.getEsCondition();
        courseNumCondition.in("courseNum",CollectionUtils.convertCollectionString(courseNumList));
        courseNumCondition.size(1000000);
        return rainstormInfoRepository.selectList(courseNumCondition);
    }

    @Override
    public void countMain(String startTime, String endTime, List<String> stationNos) {
//        startTime = TimeUtil.changeStyle(startTime, TimeUtil.WEB_FORMATOR_YMDHMS, TimeUtil.FORMATOR_YMD);
//        endTime = TimeUtil.changeStyle(endTime, TimeUtil.WEB_FORMATOR_YMDHMS, TimeUtil.FORMATOR_YMD);
        // 拿出这段时间的站点的暴雨过程
        List<RainstormInfo> rainstormInfos = selectList(startTime,endTime,CollectionUtils.convertCollectionString(stationNos));
        //根据暴雨过程标识 进行处理每个暴雨过程
        Map<String, List<RainstormInfo>> courseNumList = RectField.conversionIndexToList(rainstormInfos, "courseNum");
        // 将有时间交集的处理成一个过程  再进行站点区域筛选成一个区域
        List<RainstormTime> rainstormTimes = converRainstormTime(courseNumList);

        // 计算每个站点的区域点
        Collection<RainstormArea> rainstormAreas = rainstormAreas(rainstormTimes);

        if (CollectionUtils.isNotBlank(rainstormAreas)){
            List<RainstormInfo> rainstormInfoList = new ArrayList<RainstormInfo>();
            for (RainstormArea rainstormArea : rainstormAreas) {
                rainstormInfoList.addAll(rainstormArea.getRainstormInfoList());
            }
            rainstormInfoRepository.saveBatch(rainstormInfoList);
        }
        log.info("{}到{},持续性行标区域暴雨过程数据保存完成",startTime,endTime);
    }

    /**
     * 清除当前年的过程数据
     * @param startTime
     * @param endTime
     */
    @Override
    public void clearCourseByTime(String startTime, String endTime) {
        EsCondition esCondition = EsCondition.getEsCondition();
        esCondition.gt("time",startTime);
        esCondition.lt("time",endTime);
//        esCondition.eq("courseNum",null).not();
//        esCondition.size(1000000);
//        List<RainstormInfo> rainstormInfos = rainstormInfoRepository.selectList(esCondition);
//        rainstormInfos.stream().forEach(x -> {
//            x.setCourseNum(null);
//            x.setCourseArea(null);
//            x.setCourseContinue(null);
//            x.setNationAreaGroup(null);
//        });
        rainstormInfoRepository.deleteBySearch(esCondition);
        log.info("清除{}到{}的过程数据完成：{}",startTime,endTime);
    }


    /**
     * 转换暴雨降雨时间比较
     * @param courseNumList
     * @return
     */
    private List<RainstormTime> converRainstormTime( Map<String, List<RainstormInfo>> courseNumList){
        List<RainstormTime> rainstormTimes = new ArrayList<RainstormTime>();
        courseNumList.forEach((s, rainstormInfos) -> {
            rainstormTimes.add(new RainstormTime(rainstormInfos));
        });
        rainstormTimes.sort((o1, o2) -> {
            return (int) (o1.getStartTime()-o2.getStartTime());
        });
        return rainstormTimes;
    }


    private Collection<RainstormArea> rainstormAreas(List<RainstormTime> rainstormTimes){
        // 区域过程  key: 区域标识符号  value: 暴雨区域过程
        Map<String,RainstormArea> areaMap = new HashMap<String, RainstormArea>();
        for (RainstormTime rainstormTime : rainstormTimes) {
            if (!handlerRainstorm(rainstormTime,areaMap)){
                RainstormArea rainstormArea = new RainstormArea(rainstormTime);
                areaMap.put(rainstormArea.getAraFlag(),rainstormArea);
            }
        }
        List<RainstormArea> rainstormAreas = new ArrayList<RainstormArea>();
        areaMap.forEach((s, rainstormArea) -> {
            if (rainstormArea.getRainstormTimes().size()>=3){
                rainstormAreas.add(rainstormArea);
            }
        });
        return rainstormAreas;
    }

    /**
     * 暴雨区域过程处理
     * @param rainstormTime
     * @param areaMap
     * @return true 找到区域  false 没有找到区域
     */
    private boolean handlerRainstorm(RainstormTime rainstormTime,Map<String,RainstormArea> areaMap){
        List<String> mergeAreaFlag = new ArrayList<String>();
        for (String areaFlag:areaMap.keySet()){
            RainstormArea rainstormArea = areaMap.get(areaFlag);
            // 先进行条件判断
            if (rainstormArea.check(rainstormTime)){
                mergeAreaFlag.add(areaFlag);
            }
        }
        //找不到暴雨处理过程 返回false
        if (org.springframework.util.CollectionUtils.isEmpty(mergeAreaFlag)){
            return false;
        }
        RainstormArea rainstormArea = mergeAreaProcess(areaMap, mergeAreaFlag);
        rainstormArea.add(rainstormTime);
        //找到了暴雨过程
        return true;
    }

    /**
     * 合并区域过程
     */
    private RainstormArea mergeAreaProcess(Map<String,RainstormArea> areaMap,List<String> mergeAreaFlagList){
        RainstormArea rainstormArea = areaMap.get(mergeAreaFlagList.get(0));
        for (int i = 1; i < mergeAreaFlagList.size(); i++) {
            String areaFlag = mergeAreaFlagList.get(i);
            rainstormArea.merge(areaMap.get(areaFlag));
            areaMap.remove(areaFlag);
        }
        return rainstormArea;
    }

}
